package com.kuwou.workobject.Utils;

import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kuwou.workobject.commonality.Log;
import com.kuwou.workobject.pojo.entity.*;
import com.kuwou.workobject.service.SingerBasicInfoService;
import com.kuwou.workobject.service.SingerDetailInfoService;
import com.kuwou.workobject.service.SingerListService;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.*;
import org.slf4j.Logger;


public class CrawlSingerUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();
    private static CloseableHttpClient httpClient = HttpClients.createDefault();
    private static final Logger log = Log.getLogger(CrawlSingerUtils.class);

    private static SingerListService singerListService;
    private static SingerDetailInfoService singerDetailInfoService;
    private static SingerBasicInfoService singerBasicInfoService;

    /**
     * 设置SingerListService实现
     *
     * @param singerListService
     */
    public static void setSingerListService(SingerListService singerListService) {
        CrawlSingerUtils.singerListService = singerListService;
    }

    /**
     * 设置SingerDetailInfoService实现
     *
     * @param singerDetailInfoService
     */
    public static void setSingerDetailInfoService(SingerDetailInfoService singerDetailInfoService) {
        CrawlSingerUtils.singerDetailInfoService = singerDetailInfoService;
    }

    /**
     * 获取SingerBasicInfoService实现
     *
     * @param singerBasicInfoService
     */
    public static void setSingerBasicInfoService(SingerBasicInfoService singerBasicInfoService) {
        CrawlSingerUtils.singerBasicInfoService = singerBasicInfoService;
    }

    static {
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 执行器
     */
    public static void execute(){
        try {
            List<Artist> singerList = new ArrayList<>();
            //设置实现
            HandleSingerUtils.setSingerListService(singerListService);
            HandleSingerUtils.setSingerDetailInfoService(singerDetailInfoService);
            HandleSingerUtils.setSingerBasicInfoService(singerBasicInfoService);
            //清空相关表
            HandleSingerUtils.tTBySingerList();
            HandleSingerUtils.tTBySingerBasicInfo();
            HandleSingerUtils.tTBySingerDetailInfo();
            Document document =Jsoup.connect("https://kuwo.cn/singers")
                    .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
                    .timeout(10000)
                    .get();

            int pageNo = Integer.parseInt(document.select("ul.flex_c").select("li").last().text());

            for (int i = 1; i <= pageNo; i++) {
                log.info("正在获取第" + i + "页歌手列表");
                //获取歌手列表
                for (Artist artist : getSinger(i)) {
                    singerList.add(artist);
                }

                if (singerList.size() >= 1000 || (i == pageNo)) {
                    log.info("正在进行插入数据库操作");
                    // 执行插入操作
                    singerList = HandleSingerUtils.saveSingerBatch(singerList);
                    log.info("插入歌手列表成功");

                    Map<String, Object> singerInfo = getSingerInfo(singerList);

                    List<SingerDetailInfo> detailInfo = (List<SingerDetailInfo>) singerInfo.get("detailInfo");
                    List<SingerBasicInfo> basicInfo = (List<SingerBasicInfo>) singerInfo.get("basicInfo");
                    HandleSingerUtils.saveSingerDetailInfoBatch(detailInfo);
                    log.info("插入歌手详细信息成功");
                    HandleSingerUtils.saveSingerBasicInfoBatch(basicInfo);
                    log.info("插入歌手基本信息成功");
                    singerList.clear();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                if(httpClient != null) httpClientClose();
                log.info("httpClient关闭成功");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 获取歌手列表
     *
     * @return List<Artist>
     */
    public static List<Artist> getSinger(int pageNum) {
        String url = "https://wapi.kuwo.cn/api/www/artist/artistInfo?category=0&";
        List<Artist> artistList = new ArrayList<>();
        String param = "pn=" + pageNum + "&rn=60";
        HttpGet httpGet = new HttpGet(url + param);
        httpGet.setHeader("Accept", "application/json");
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36");

        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
            // 解析JSON（此时会忽略未知字段）
            ArtistResponse artistResponse = objectMapper.readValue(responseBody, ArtistResponse.class);

            if (artistResponse.getCode() == 200 && "success".equals(artistResponse.getMsg())) {
                artistList = artistResponse.getData().getArtistList();
            }

        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return artistList;
    }

    /**
     * 获取歌手信息
     */
    public static Map<String, Object> getSingerInfo(List<Artist> singerList) throws IOException {
        String url = "https://kuwo.cn/singer_detail/";
        Map<String, Object> infoData = new HashMap<>();
        List<SingerDetailInfo> singerDetailInfoList = new ArrayList<>();
        List<SingerBasicInfo> SingerBasicInfoList = new ArrayList<>();

        for (int i = 0; i <= singerList.size() - 1; i++) {
            // 创建 GET 请求
            HttpGet httpGet = new HttpGet(url + singerList.get(i).getId() + "/info");
            // 设置请求头
            httpGet.setHeader("Accept", "application/json");
            // 发送请求并获取响应
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                // 获取响应体
                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                Document parse = Jsoup.parse(responseBody);
                singerDetailInfoList.add(handleDetailInfo(parse, singerList.get(i)));
                SingerBasicInfoList.add(handleBasicInfo(parse,singerList.get(i)));
            }
        }
        infoData.put("detailInfo", singerDetailInfoList);
        infoData.put("basicInfo", SingerBasicInfoList);
        return infoData;

    }

    /**
     * 处理基本信息
     */
    public static SingerBasicInfo handleBasicInfo(Document parse, Artist singer) {
        Elements infoData = parse.getElementsByClass("info_items");
        Elements data = parse.getElementsByClass("info_list flex_c");
        String gender = "-";
        String nationality = "-";
        String language = "-";
        String fans = "-";
        if (!data.isEmpty()){
            gender = cleanString(data.get(1).select("div.item_l").first().text()).split(":")[1];
            nationality = cleanString(data.get(1).select("div.item_r").first().text()).split(":")[1];
            language = cleanString(data.get(2).select("div.item_r").text()).split(":")[1];
            fans = infoData.select("span.num").get(3).text();
        }

        String englishName = singer.getAartist().equals("") ? "无" : singer.getAartist();
        return new SingerBasicInfo(
                singer.getSingerId(),englishName,
                singer.getPic(), gender, fans,
                singer.getAlbumNum(), singer.getMvNum(), singer.getMusicNum(),
                nationality,language.replace(";","")
        );
    }

    /**
     * 处理详细信息
     * @return SingerDetailInfo
     */
    public static SingerDetailInfo handleDetailInfo(Document parse, Artist singer) {
        Elements infoData = parse.getElementsByClass("info_list flex_c");
        List<String> data = new ArrayList<>();
        Map<String, String> infoMap = new HashMap<>();
        for (Element infoDatum : infoData) {
            Element d1 = infoDatum.select("div.item_l").first();
            Element d2 = infoDatum.select("div.item_r").first();
            for (Element element : List.of(d1, d2)) {
                data.add(cleanString(element.text()));
            }
        }
        for (String info : data) {
            String[] split = info.split(":");
            infoMap.put(split[0], split[1]);
        }

        Element background = parse.select("p.info").first();
        String backgroundText = background == null ? "无" : background.text();
        infoMap.put("个人简介", backgroundText);

        return new SingerDetailInfo(
                singer.getSingerId(), infoMap.get("出生地"),
                infoMap.get("生日"), infoMap.get("星座"),
                infoMap.get("身高"), infoMap.get("体重"),
                infoMap.get("个人简介")
        );
    }

    /**
     * 关闭httpClient
     */
    public static void httpClientClose() throws IOException {
        httpClient.close();
    }

    /**
     * 字符串清洗
     * @return String
     */
    public static String cleanString(String data) {
        return data.replace("： ", ":")
                .replace("：", ":")
                .replace(";", "")
                .trim();
    }
}

